/*
 * Filename:  SafeService.java
 * Copyright:  Raisecom Technologies Co., Ltd. Copyright YYYY-YYYY,  All rights reserved
 * Description:  <description>
 * Author:  donghu
 * Edit-time:  2016-5-4
 * Modify content:  <modify content>
 */
package com.gutetec.cms.usmc.wrapper;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Random;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import net.sf.json.JSONObject;

import com.gutetec.cms.usmc.bean.LoginInfo;
import com.gutetec.cms.usmc.bean.LoginResult;
import com.gutetec.cms.usmc.bean.UserInfo;
import com.gutetec.cms.usmc.db.dao.SafeDao;
import com.gutetec.cms.usmc.db.util.UsmcDBUtil;
import com.gutetec.cms.usmc.util.UsmcUtil;

/**
 * <Security policy business process>
 * <Security policy business process>
 * @author  donghu
 * @version  [version, 2016-5-4]
 * @see  [class/function]
 * @since  [version]
 */
public class SafeService
{
    private static final Logger LOGGER = LoggerFactory.getLogger(SafeService.class);
    
    private static final String TAG = "SafeService";
    
    
    private static HashMap<String, UserSessionTask> sessionTaskMap = new HashMap<String, UserSessionTask>();
    
    private static SafeService instance = new SafeService();
    
    private static SafeDao safeDao = (SafeDao)UsmcDBUtil.getDaoInstance("SAFE");
    
    private UserInfo loginInfo = new UserInfo();
    
    public synchronized static SafeService getInstance()
    {
        return instance;
    }
    
    public boolean[] checkRight(String[] operations)
    {
        if (operations != null)
        {
            boolean[] value = new boolean[operations.length];
            for (int i = 0; i < value.length; i++)
            {
                value[i] = true;
            }
            return value;
        }
        return new boolean[0];
    }
    
    public boolean getSessionTaskMapKey(String userName)
    {
    	
	    Iterator it = sessionTaskMap.entrySet().iterator();
	    while(it.hasNext())
	    { 
	    	java.util.Map.Entry entry = (java.util.Map.Entry)it.next();  
	        if(entry.getKey().equals(userName))
	        {	        	
	        	return true;
	        }
	    }
	    return false;
    }
    /** 
    * @Title doLogin 
    * @Description TODO(check user Login Info ) 
    * @param userlogininfo
    * @param requestIpAddr   
    * @return LoginResult    
    */
    
    
    public LoginResult doLogin(LoginInfo userlogininfo)
    {
        String result = LoginResult.MSG_FAILED;
        int code = LoginResult.FAILED;
        String sessioncode = null;
        /*if(getSessionTaskMapKey(userlogininfo.getUsername()))
        {
        	result = LoginResult.MSG_ALREADY_LOGIN;
        	return new LoginResult(code, result, loginInfo);
        }  */      
        
        loginInfo = safeDao.loginByName(userlogininfo.getUsername());
        
        // check binding IP
        if (true)
        {
            // check account expire
            if (true)
            {
                // check password expire
                if (true)
                {
                    // check password correct
                    if (null != loginInfo && userlogininfo.getUsername().equals(loginInfo.getUserName())
                        && userlogininfo.getPassword().equals(loginInfo.getUserPasswd()))
                    {
                        
                        // check login number of times
                        if (!UsmcUtil.USMC_SUPER_MANAGER.equals(loginInfo.getUserName())
                            && 0 >= Integer.parseInt(loginInfo.getUserLoginCount()))
                        {
                            result = LoginResult.MSG_FAILED_FIRST_LOGIN;
                        }
                        else
                        // login success
                        {
                            code = LoginResult.SUCCESS;
                            result = LoginResult.MSG_SUCCESS;
                            sessioncode = getRandomString(10);
                            // set user session timer
                            startUserTimetask(sessioncode);
                            
                            // update login number of times and login time
                            setUserLoginInfo(loginInfo.getUserName());
                        }
                    }
                    else
                    {
                        result = LoginResult.MSG_FAILED;
                    }
                }
                else
                {
                    result = LoginResult.MSG_FAILED_ACCOUNT_EXPIRE;
                }
            }
            else
            {
                result = LoginResult.MSG_FAILED_ACCOUNT_EXPIRE;
            }
        }
        else
        {
            result = LoginResult.MSG_FAILED_BIND_IP_ERROR;
        }
        
        return new LoginResult(code, result, loginInfo,sessioncode);
    }
    
    /** 
    * @Title modify password 
    * @Description TODO(user modify password ) 
    * @param userinfo      
    * @return void    
    */
    public JSONObject modifyPwd(int type, JSONObject pwdinfo)
    {
        String userUame = pwdinfo.get("username").toString();
        String oldPwd = pwdinfo.get("oldpassword").toString();
        String newPwd = pwdinfo.get("newpassword").toString();
        JSONObject object = new JSONObject();
        String isForces = "1";// forces modify password default
        String result = "0";// modify password success default
        
        UserInfo userinfo = safeDao.loginByName(userUame);
        
        if (userinfo.getUserPasswd().equals(oldPwd))
        {
            if (safeDao.modifyPassword(userUame, newPwd))
            {
                if (UsmcUtil.LOGIN_MODIFY_PWD == type)
                {
                    isForces = "0";// not forces modify password
                }                
            }
            else
            {
                result = "1";// modify password failed
            }
        }
        else
        {
            result = "2";// old password error
        }
        
        object.put("result", result);
        object.put("isforces", isForces);
        return object;
    }
    
    /** 
    * @Title modify password 
    * @Description TODO(user modify password ) 
    * @param userinfo      
    * @return void    
    */
    public JSONObject resetPwd(JSONObject pwdinfo)
    {
        String userUame = pwdinfo.get("username").toString();
        String newPwd = pwdinfo.get("newpassword").toString();
        JSONObject object = new JSONObject();
        String result = "0";// modify password success default
        
        if (safeDao.modifyPassword(userUame, newPwd))
        {
            result = "0";// modify password success
        }
        else
        {
            result = "1";// modify password failed
        }
        
        object.put("result", result);
        return object;
    }
    
    /** 
    * @Title doLogout 
    * @Description TODO(user Logout and remove User's requestIpAddr) 
    * @param requestIpAddr      
    * @return void    
    */
    public void doLogout(String username)
    {
        // cancel timetask
        if (!UsmcUtil.isEmpty(username))
        {
            getUserTimetask(username).stop();
            removeUserTimetask(username);
        }
        
    }
    
    /** 
    * @Title getUserSession
    * @Description TODO(get user login info by requestIpAddr) 
    * @param requestIpAddr    
    * @return String    
    */
    public String getUserSession(String sessioncode)
    {
    	UserSessionTask userTask = getUserTimetask(sessioncode);
        if(null != userTask)
        {
        	userTask.updateSessionTime(UsmcUtil.USER_SESSION_TIME * UsmcUtil.ONE_MIN);
        	return "true";
        }
        return "false";
    }
    
    /**
     * <get curr user session time>
     * <Detailed description of function>
     * @param requestIpAddr
     * @return
     * @see [class/function]
     */
    public String getUserSessionTime(String userName)
    {
        if (!UsmcUtil.isEmpty(userName))
        {
            if (null != getUserTimetask(userName))
            {
                return getUserTimetask(userName).getSessionTime() + "";
            }
        }
        return "";
    }  
    
    
    /**
     * <get user login info>
     * <Detailed description of function>
     * @return
     * @see [class/function]
     */
    public UserInfo getLoginInfo()
    {
        return loginInfo;
    }
    
    /**
     * <set user login info>
     * <Detailed description of function>
     * @param loginInfo
     * @see [class/function]
     */
    public void setLoginInfo(UserInfo loginInfo)
    {
        this.loginInfo = loginInfo;
    }
    
    /**
     * <add user timer task obj to map>
     * <Detailed description of function>
     * @param userName
     * @param timerTask
     * @see [class/function]
     */
    private synchronized void addUserTimetask(String sessioncode, UserSessionTask timerTask)
    {
        UserSessionTask tempTask = sessionTaskMap.get(sessioncode);
        if (null != tempTask)
        {
            tempTask.stop();
            sessionTaskMap.remove(sessioncode);
        }
        sessionTaskMap.put(sessioncode, timerTask);
    }
    
    /**
     * <delete user timer task obj from map>
     * <Detailed description of function>
     * @param userName
     * @param timerTask
     * @see [class/function]
     */
    private synchronized void removeUserTimetask(String sessioncode)
    {
        sessionTaskMap.remove(sessioncode);
    }
    
    /**
     * <get user timer task obj from map>
     * <Detailed description of function>
     * @param userName
     * @param timerTask
     * @see [class/function]
     */
    private synchronized UserSessionTask getUserTimetask(String sessioncode)
    {
        return sessionTaskMap.get(sessioncode);
    }
    
    /**
     * <start user timer when login success>
     * <Detailed description of function>
     * @param userName
     * @see [class/function]
     */
    public synchronized void startUserTimetask(String sessioncode)
    {
        UserSessionTask userTask =
            new UserSessionTask(sessioncode,UsmcUtil.USER_SESSION_TIME * UsmcUtil.ONE_MIN);
        userTask.start();
        addUserTimetask(sessioncode, userTask);
    }
    
    /**
     * <update user info when login success>
     * <Detailed description of function>
     * @param userName
     * @see [class/function]
     */
    public synchronized void setUserLoginInfo(String userName)
    {
        safeDao.updateUserloginInfo(userName);
    }
    
    /**
     * <get username from cookie >
     * <Detailed description of function>
     * @param userName
     * @see [class/function]
     */
    public String getCookieUser(HttpServletRequest request)
    {
    	Cookie[] cookie = request.getCookies();
    	if(null != cookie)
    	{
    		for (int i = 0; i < cookie.length; i++) 
        	{
        		Cookie cook = cookie[i];
        		if(cook.getName().equalsIgnoreCase("username"))
        		{
        			return cook.getValue().toString();    
        		}
        	}
    	}    	
    	return "";
    }
    
    public String getCookieSessioncode(HttpServletRequest request)
    {
    	Cookie[] cookie = request.getCookies();
    	if(null != cookie)
    	{
    		for (int i = 0; i < cookie.length; i++) 
        	{
        		Cookie cook = cookie[i];
        		if(cook.getName().equalsIgnoreCase("sessioncode"))
        		{
        			return cook.getValue().toString();    
        		}
        	}
    	}    	
    	return "";
    }
    
    /**
     * <update user lifecycle timer>
     * <Detailed description of function>
     * @param userName
     * @see [class/function]
     */
    public void updataUserTimers(String sessioncode)
    {
    	getUserTimetask(sessioncode).updateTimers();
    }
    
    /**
     * <manger of user session>
     * <Function details>
     * @author  donghu
     * @version  [Version, 2016-5-28]
     * @see  [Classs/Method]
     * @since  [Product/Model Version]
     */
    class UserSessionTask
    {
        
        private ScheduledThreadPoolExecutor timer;
        
        private String sessioncode;
        private int sessionTime;
        private int timers = UsmcUtil.USER_SESSION_TIMERS;;
        
        public UserSessionTask(String sessioncode,int time)
        {
            this.timer = new ScheduledThreadPoolExecutor(5);
            this.sessioncode = sessioncode;
            this.sessionTime = time;
        }
        
        private class UserTask implements Runnable 
        {
            
            @Override
            public void run()
            {
                if (0 >= sessionTime || 0 == timers)
                {
                    removeUserTimetask(sessioncode);
                    LOGGER.info(TAG, "sessioncode " + sessioncode + " session timeout!");
                    
                    timer.shutdown();  
                }
                sessionTime = sessionTime - UsmcUtil.USER_SESSION_PERIOD * 1000;
                //timers --;
            }
            
        }
        
        
        /**
         * <update user session timer>
         * <Detailed description of function>
         * @param sessionTime
         * @see [class/function]
         */
        public void updateSessionTime(int sessionTime)
        {
            this.sessionTime = sessionTime;
        }
        
        /**
         * <update user session timer>
         * <Detailed description of function>
         * @param sessionTime
         * @see [class/function]
         */
        public void updateTimers()
        {
            this.timers = UsmcUtil.USER_SESSION_TIMERS;
        }
        
        /**
         * <get curr user session time>
         * <Detailed description of function>
         * @return
         * @see [class/function]
         */
        public int getSessionTime()
        {
            return this.sessionTime;
        }
        
        /**
         * <start user timer>
         * <Detailed description of function>
         * @see [class/function]
         */
        public void start()
        {
            try
            {
                UserTask task = new UserTask();
                timer.scheduleWithFixedDelay(task, 1, UsmcUtil.USER_SESSION_PERIOD, TimeUnit.SECONDS);  
            }
            catch (Exception e)
            {
                timer.shutdown();
            }
        }
        
        /**
         * <stop user timer>
         * <Detailed description of function>
         * @see [class/function]
         */
        public void stop()
        {
            timer.shutdown();
        }
        
    }
    
    public static String getRandomString(int length) {
        String base = "abcdefghijklmnopqrstuvwxyz0123456789";     
        Random random = new Random();     
        StringBuffer sb = new StringBuffer();     
        for (int i = 0; i < length; i++) {     
            int number = random.nextInt(base.length());     
            sb.append(base.charAt(number));     
        }     
        return sb.toString();     
     }     
    
}
